package it.scambiocorse.dao;

import it.scambiocorse.model.ClienteType;
import it.scambiocorse.model.FeedBackType;
import it.scambiocorse.model.JTableType;
import it.scambiocorse.model.ServizioJson;
import it.scambiocorse.model.ServizioType;
import it.scambiocorse.rowmapper.ClientiRowMapper;
import it.scambiocorse.rowmapper.FeedbackRowMapper;
import it.scambiocorse.rowmapper.ServizioRowMapper;
import it.scambiocorse.utils.Costanti;
import it.scambiocorse.utils.Utils;

import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor;
import org.springframework.transaction.annotation.Transactional;

public class FeedbackDao extends JdbcDaoSupport implements FeedbackService {
	
	final Logger logger = Logger.getLogger(getClass());
	
  protected void initDao() throws Exception {
    super.initDao();
    getJdbcTemplate().setNativeJdbcExtractor(new SimpleNativeJdbcExtractor());

  }
	
	
	@Transactional
	public int inserisciFeedback(FeedBackType f) throws Exception {
	  
			String metodo = "inserisciFeedback(...) - ";
			logger.warn(metodo+"Inizio");
		  Number idFeed = 0;
		  String sql = "call inserisciFeedback(?,?,?)";
		  try{ 
		  	
		  	 SimpleJdbcCall caller = new SimpleJdbcCall(getJdbcTemplate())
		  	.withFunctionName("inserisciFeedback");
		  	
		  	 Map<String, Object> map = new HashMap<String, Object>(16);
					
		  	 map.put("idFeed", f.getIdFeed());
		  	 map.put("tipoFeed", f.getTipoFeedback());
		  	 map.put("feedBack", f.getFeedback());
		  	 
		  	 
		  	 idFeed = caller.executeFunction(Number.class, map);

		  	if (idFeed.intValue() > 0) {
		  		logger.warn(metodo+" Esito: OK, feedback INSERITO, idFeed = "+idFeed.intValue());
		  	} else {
		  		idFeed = 0;
		  		logger.warn(metodo+" Attenzione: feedback NON INSERITO");
		  	}
		  	
		  } catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  }
		  
		  logger.warn(metodo+" Fine");
		return idFeed.intValue();
	}

	
	public ArrayList<FeedBackType> listaFeedbackIn(int idUser) throws Exception {

			String metodo = "listaFeedbackIn(...)";
			logger.warn(metodo+" - Inizio");
		  ResultSet rs = null; 
		  List ret = null;
		  String sql = "select feed_tab.*, utente_tab.id_user, utente_tab.login from feed_tab join utente_tab on feed_tab.id_user_inse = utente_tab.id_user " +
		  		"where feed_tab.id_user = ? and feed_tab.data_fine is not null";// = null ";
		  try{ 
		  	
		  	logger.warn(metodo+" - Chiamata SQL = "+sql+" iduser = "+idUser);
		  	ret = (List<FeedBackType>) getJdbcTemplate().query(sql, new Object[] { idUser }, new FeedbackRowMapper());
		  	logger.warn(metodo+" Esito: OK, grandezza lista "+ret.size());
		  	
		  	if (ret != null && ret.size() > 0) {
				  logger.warn(metodo+"La lista e' PIENA");
		  	} else {
				  logger.warn(metodo+"La lista e' VUOTA");
		  		
		  	}
		  
		  } catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  }
		  
		  logger.warn(metodo+" Fine");
		  
		  
			return (ArrayList<FeedBackType>)ret;
		
	}
	
	public int pendingIn(int idUser) throws Exception {

		String metodo = "pendingIn(...)";
		logger.warn(metodo+" - Inizio");
	  int ret = 0;
	  String sql = "select count(id_feed) from feed_tab where id_user = ? and tipo_feedback = 0";
	  try{ 
	  	
	  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+idUser);
	  	ret =  getJdbcTemplate().queryForInt(sql, new Object[] { idUser });
	  	logger.warn(metodo+" Esito: OK, valore estratto = "+ret);
	  	
	  } catch (Exception e) {
	  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
	  	logger.error(e);
	  }
	  
	  logger.warn(metodo+" Fine");
	  
		return ret;
	}
	
	public int pendingOut(int idUser) throws Exception {

		String metodo = "pendingOut(...)";
		logger.warn(metodo+" - Inizio");
	  ResultSet rs = null; 
	  int ret = 0;
	  String sql = "select count(id_feed) from feed_tab where id_user_inse = ? and tipo_feedback = 0";
	  try{ 
	  	
	  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+idUser);
	  	ret =  getJdbcTemplate().queryForInt(sql, new Object[] { idUser });
	  	logger.warn(metodo+" Esito: OK, valore estratto = "+ret);
	  	
	  } catch (Exception e) {
	  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
	  	logger.error(e);
	  }
	  
	  logger.warn(metodo+" Fine");
	  
		return ret;
	}	
	
	
	public ArrayList<FeedBackType> listaFeedbackOut(int idUser) throws Exception {
		String metodo = "listaFeedbackOut(...)";
		logger.warn(metodo+" - Inizio");
	  ResultSet rs = null; 
	  List ret = null;
	  String sql = "SELECT * FROM feed_tab where id_user_inse = ? and negapos is not NULL";
	  try{ 
	  	
	  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+idUser);
	  	ret = (List<FeedBackType>) getJdbcTemplate().query(sql, new Object[] { idUser }, new FeedbackRowMapper());
	  	logger.warn(metodo+" Esito: OK, grandezza lista "+ret.size());
	  // Do whatever I want with resultset here... 
	  } catch (Exception e) {
	  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
	  	logger.error(e);
	  }
	  
	  logger.warn(metodo+"La lista e' "+((ret == null) ? "NULL" : "PIENA"));
	  logger.warn(metodo+" Fine");
	  
	  
		return (ArrayList<FeedBackType>)ret;
	
	}

	public ArrayList<FeedBackType> listaFeedbackPendingIn(int idUser) throws Exception {
		String metodo = "listaFeedbackPendingIn(...)";
		logger.warn(metodo+" - Inizio");
	  ResultSet rs = null; 
	  List ret = null;
	  String sql = "select feed_tab.*, utente_tab.id_user, utente_tab.login from feed_tab join utente_tab on feed_tab.id_user_inse = utente_tab.id_user  where " +
	  		"feed_tab.tipo_feedback = 0 and feed_tab.id_user = ?";
	  try{ 
	  	
	  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+idUser);
	  	ret = (List<FeedBackType>) getJdbcTemplate().query(sql, new Object[] { idUser }, new FeedbackRowMapper());
	  	logger.warn(metodo+" Esito: OK, grandezza lista "+ret.size());
	  // Do whatever I want with resultset here... 
	  } catch (Exception e) {
	  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
	  	logger.error(e);
	  }
	  
	  logger.warn(metodo+"La lista e' "+((ret == null) ? "NULL" : "PIENA"));
	  logger.warn(metodo+" Fine");
	  
	  
		return (ArrayList<FeedBackType>)ret;
	}

	public ArrayList<FeedBackType> listaFeedbackPendingOut(int idUser) throws Exception {
		String metodo = "listaFeedbackPendingOut(...)";
		logger.warn(metodo+" - Inizio");
	  ResultSet rs = null; 
	  List ret = null;
	  String sql = "select feed_tab.*, utente_tab.id_user, utente_tab.login from feed_tab join utente_tab on feed_tab.id_user = utente_tab.id_user where " +
		  		"feed_tab.tipo_feedback = 0 and feed_tab.id_user_inse = ?";
	  try{ 
	  	
	  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+idUser);
	  	ret = (List<FeedBackType>) getJdbcTemplate().query(sql, new Object[] { idUser }, new FeedbackRowMapper());
	  	logger.warn(metodo+" Esito: OK, grandezza lista "+ret.size());
	  // Do whatever I want with resultset here... 
	  } catch (Exception e) {
	  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
	  	logger.error(e);
	  }
	  
	  logger.warn(metodo+"La lista e' "+((ret == null) ? "NULL" : "PIENA"));
	  logger.warn(metodo+" Fine");
	  
	  
		return (ArrayList<FeedBackType>)ret;
	}
	
	public FeedBackType getFeedback(int idFeed) throws Exception {
		String metodo = "getFeedback(...)";
		logger.warn(metodo+" - Inizio");
		FeedBackType f = null;
		  String sql = "select feed_tab.*, utente_tab.id_user, utente_tab.login from feed_tab join utente_tab on feed_tab.id_user_inse = utente_tab.id_user where feed_tab.id_feed = ?  ";

	  try{ 
	  	
	  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+idFeed);
	  	f = (FeedBackType) getJdbcTemplate().queryForObject(sql, new Object[] { idFeed }, new FeedbackRowMapper());
	  	logger.warn(metodo+" Esito: OK, feedback estratto: "+f.getFeedback());
	  } catch (Exception e) {
	  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
	  	logger.error(e);
	  }
	  
	  logger.warn(metodo+" Fine");
	  
	  
		return f;
	}

	public FeedBackType getFeedbackOut(int idUser, int idServ)throws Exception{
		String metodo = "getFeedbackOut(...)";
		logger.warn(metodo+" - Inizio");
		FeedBackType f = null;
	  String sql = "SELECT * FROM feed_tab where id_user_inse = ? and id_serv = ?";
	  try{ 
	  	
	  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+idUser+" ? = "+idServ);
	  	f = (FeedBackType) getJdbcTemplate().queryForObject(sql, new Object[] { idUser,idServ }, new FeedbackRowMapper());
	  	logger.warn(metodo+" Esito: OK, feedback estratto: "+f.getFeedback());
	  } catch (Exception e) {
	  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
	  	logger.error(e);
	  }
	  
	  logger.warn(metodo+" Fine");
	  
	  
		return f;
	}
	
	
	 public HashMap listaFeedbackJTable(int idUser, JTableType j) throws Exception {
			String metodo = "listaFeedbackJTable(...) - ";
			logger.warn(metodo+"Inizio");
		
			  List ret = null;
			  String sql = "";
			  	HashMap jOut = null;
				try{ 	
						
						 Object[] args = null;
						 					  
						  if (Utils.isValid(j.getJtSorting())) { // AJAX CON SORTING & PAGING
							  
							  sql =  "select feed_tab.*, utente_tab.id_user, utente_tab.login from feed_tab join utente_tab on feed_tab.id_user_inse = utente_tab.id_user " +
								  		"where feed_tab.id_user = ? and feed_tab.data_fine is not null  ORDER BY "+decodeColumn(j.getJtSorting())+" LIMIT ?,?";
							  logger.warn("Select con SORTING & PAGING  jtStartIndex = "+j.getJtStartIndex()+" jtPageSize = "+j.getJtPageSize());
						  } else {										// AJAX SOLO PAGING
							  sql =  "select feed_tab.*, utente_tab.id_user, utente_tab.login from feed_tab join utente_tab on feed_tab.id_user_inse = utente_tab.id_user " +
								  		"where feed_tab.id_user = ? and feed_tab.data_fine is not null LIMIT ?,?";
							  logger.warn("Select con SOLO con PAGING -- jtStartIndex = "+j.getJtStartIndex()+" jtPageSize = "+j.getJtPageSize());
						  }
						  
						  	args = new Object[] {idUser, j.getJtStartIndex(),j.getJtPageSize() };
						  	logger.warn(metodo+" - Chiamata SQL = "+sql+" , ? = ");
						  	ret = (List<FeedBackType>) getJdbcTemplate().query(sql, args , new FeedbackRowMapper());
						  	logger.warn( metodo+" Esito: OK, grandezza lista "+ret.size() );
						  	
						  	int totRows = 0;
						  	if (ret.size() > 0) {
								logger.warn("PRENDO IL TOTALE PER JTABLE");
								sql = "SELECT count(*) from feed_tab s where s.id_user = ?";
								totRows =  getJdbcTemplate().queryForInt(sql, args = new Object[] {idUser} );
						  	}
						  	
						  	
						  	
						  	jOut = new HashMap<String, Object>();
							jOut.put("Result", "OK");
							jOut.put("Records", ret);
							jOut.put("TotalRecordCount", totRows);
			
						  	logger.warn( metodo+" Esito: OK, grandezza lista "+ret.size() );
				  } catch (Exception e) {
				  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
				  	logger.error(e);
				  	throw e;
				  }
		  
		    logger.warn(metodo+" Fine");
			return jOut;
		}
	
	 private String decodeColumn(String j) {
			String ret = "";
			
			if (j.startsWith("idServUser")) {
				ret = "id_serv_user";
			}
			
			else if (j.startsWith("dataora"))
				ret = "dataora";
			
			else if (j.startsWith("volo"))
				ret = "volo";
			
			else if (j.startsWith("pickUp"))
				ret = "pick_up";
			
			
			return ret;
	 }		

	public FeedBackType getFeedbackIn(int idUser, int idServ) throws Exception {
			String metodo = "getFeedbackIn(...)";
			logger.warn(metodo+" - Inizio");
			FeedBackType f = null;
		  String sql = "SELECT * FROM feed_tab where id_user = ? and id_serv = ?";
		  try{ 
		  	
		  	logger.warn(metodo+" - Chiamata SQL = "+sql+" ? = "+idUser+" ? = "+idServ);
		  	f = (FeedBackType) getJdbcTemplate().queryForObject(sql, new Object[] { idUser,idServ }, new FeedbackRowMapper());
		  	logger.warn(metodo+" Esito: OK, feedback estratto: "+f.getFeedback());
		  } catch (Exception e) {
		  	logger.warn(metodo+" Si e' verificato un errore GENERICO durante la seguente chiamata  \""+sql);
		  	logger.error(e);
		  }
		  
		  logger.warn(metodo+" Fine");
		return f;
	}

}